/*
   Copyright 2012 Dmitry Bratus

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using System.Collections.Generic;
using Flower.Logging;
using Flower.Services;
using Flower.Services.Data;
using Flower.Workflow;
using SortOrder = Flower.Services.Data.SortOrder;

namespace Flower.Client
{
    /// <summary>
    /// The directory client interface.
    /// </summary>
    public interface IFlowerClient : IServicesProvider, ILockManager, IDisposable
    {
        /// <summary>
        /// The directory.
        /// </summary>
        IDirectory Directory { get; }

        /// <summary>
        /// Starts a process.
        /// </summary>
        /// <typeparam name="TIn">Input argument type.</typeparam>
        /// <typeparam name="TOut">Return value type.</typeparam>
        /// <param name="workflow">Path or id of a workflow. If a local path is provided (doesn't start with /), it is prepended with '/Workflows/'.</param>
        /// <param name="args">Input argument.</param>
        /// <param name="log">Log to be used by the workflow initializer.</param>
        /// <returns>The value returned by the Start method of the workflow type.</returns>
        ProcessStartResult<TOut> StartProcess<TIn, TOut>(string workflow, TIn args, Log log);

        /// <summary>
        /// Returns messages from a specified subset sorted by a specified property.
        /// </summary>
        /// <typeparam name="TMsg">Message type.</typeparam>
        /// <param name="subset">The subset.</param>
        /// <param name="property">The property to sort by.</param>
        /// <param name="order">The sort order.</param>
        /// <param name="offset">The index of the first returned entry among found.</param>
        /// <param name="limit">Upper limit on the indexes to return so that max. entries returned = limit - offset.</param>
        /// <returns>Array of found messages or an empty array if no messages found.</returns>
        IList<Message<TMsg>> GetMessages<TMsg>(string subset, SortProperty property, SortOrder order, long offset, long limit);

        /// <summary>
        /// Returns a single message by id or path.
        /// </summary>
        /// <typeparam name="TMsg">Type of the message.</typeparam>
        /// <param name="which">Id or path of the message entry.</param>
        /// <returns>The message or null if the message with the specified id or path doesn't exist.</returns>
        Message<TMsg> GetMessage<TMsg>(string which);

        /// <summary>
        /// Puts a single message to a subset.
        /// </summary>
        /// <typeparam name="TMsg">Message type.</typeparam>
        /// <param name="subset">The subset.</param>
        /// <param name="name">The name to assign to the message.</param>
        /// <param name="message">The message to put.</param>
        /// <param name="format">
        /// Serialization format of the message. 
        /// BinXml is recommended for small messages;
        /// GZipXml is recommended for large messages (>1Kb); 
        /// TextXml should be used for debug only.
        /// </param>
        /// <returns>True if the message has been put successfully; otherwise, false.</returns>
        bool PutMessage<TMsg>(string subset, string name, TMsg message, BlobFormat format);

        /// <summary>
        /// Puts multiple messages to a subset.
        /// </summary>
        /// <typeparam name="TMsg">Message type.</typeparam>
        /// <param name="subset">The subset.</param>
        /// <param name="names">
        /// Names to assign to the messages. Each name is assigned to the message,
        /// with the matching index in the messages list. If the name list contains null under the
        /// corresponding index, then default name is assigned. If the names list is null, 
        /// default names are used for all messages.
        /// </param>
        /// <param name="messages">The messages to put.</param>
        /// <param name="format">
        /// Serialization format of the message. 
        /// BinXml is recommended for small messages;
        /// GZipXml is recommended for large messages (>1Kb); 
        /// TextXml should be used for debug only.
        /// </param>
        /// <returns>
        /// The number of messages successfully put. The the returned value is less than messages.Count,
        /// then the size limit of the set has been reached. Messages are put sequentially, so that
        /// if the call returned n, than the first n messages has been put.
        /// </returns>
        int PutMessages<TMsg>(string subset, IList<string> names, IList<TMsg> messages, BlobFormat format);

        /// <summary>
        /// Removes a message releasing waiters if any.
        /// </summary>
        /// <param name="message">Path of id of the message.</param>
        void RemoveMessage(string message);

        /// <summary>
        /// Creates a script to execute in the dictionary used by the client.
        /// </summary>
        /// <returns>The new script.</returns>
        Script CreateScript();

        /// <summary>
        /// Injects services into members marked with Service attribute.
        /// </summary>
        /// <param name="target">The object which will recieve the services.</param>
        void InjectServices(object target);

        /// <summary>
        /// Registers a callback message recipient.
        /// </summary>
        /// <typeparam name="TMsg">The type of the message.</typeparam>
        /// <param name="recipient">The id of the recipient.</param>
        /// <param name="handler">The message handler.</param>
        void AddRecipient<TMsg>(string recipient, Action<TMsg> handler);

        /// <summary>
        /// Unregisters a callback recipient.
        /// </summary>
        /// <param name="recipient">The id of the recipient.</param>
        void RemoveRecipient(string recipient);

        /// <summary>
        /// Returns an instance of a queue of a process.
        /// </summary>
        /// <param name="pid">Id of the process.</param>
        /// <returns>An instance of a queue of a process.</returns>
        IQueueService GetProcessQueue(string pid);
    }
}